package com.cqupt.scanning.system.file.helper;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cqupt.scanning.handler.exception.MyException;
import com.cqupt.scanning.system.acl.entity.AclUser;
import com.google.common.primitives.Bytes;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.ss.formula.functions.T;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Data: 2021/7/13 15:37
 * @Author: 宋宝梁
 */
@Slf4j
public class DownloadFileHelper {


    public static void downloadOneFile(String filePath, String description, HttpServletResponse response) {
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            JSONObject jsonObject = new JSONObject();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/plain;charset=utf-8");

            if (filePath == null || filePath.isEmpty()) {
                jsonObject.put("status", 20001);
                jsonObject.put("message", "文件路径异常");
                response.getWriter().write(JSON.toJSONString(jsonObject));
                return;
            }

            File file = new File(filePath);
            if (!file.exists()) {
                jsonObject.put("status", 20001);
                jsonObject.put("message", "文件不存在");
                response.getWriter().write(JSON.toJSONString(jsonObject));
                return;
            }

            String fileName = file.getName();
            // 配置文件下载
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            // 下载文件能正常显示中文
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

            // 实现文件下载
            byte[] buffer = new byte[1024 * 8];
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            OutputStream os = response.getOutputStream();
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }
            log.info(description, fileName);
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(20001, "文件下载异常");
        } finally {
            try {
                if (bis != null) bis.close();
                if (fis != null) fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void downloadBatchFiles(byte[] zipFile, HttpServletRequest request,HttpServletResponse response) {
        //响应头的设置
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/octet-stream");
        response.setHeader("Accept-Ranges", "bytes");
        //设置压缩包的名字
        String dates = DateFormatUtils.format(new Date(), "yyyy-MM-dd");//获取时间戳
        String billname = "file" + dates;
        String downloadName = billname + ".zip";
        //返回客户端浏览器的版本号、类型
        String agent = request.getHeader("User-Agent");
        try {
            //针对IE或者以IE为内核的浏览器：
            if (agent.contains("MSIE") || agent.contains("Trident")) {
                downloadName = URLEncoder.encode(downloadName, "UTF-8");
            } else {
                //非IE浏览器的处理：
                downloadName = new String(downloadName.getBytes("UTF-8"), "ISO-8859-1");
            }
        } catch (Exception e) {
            e.printStackTrace();
            response.setContentType("application/json");
            throw new MyException(20001, "文件下载异常");
        }
        response.setHeader("Content-Disposition", "attachment;fileName=" + downloadName);//设置下载名称
        try {
            response.getOutputStream().write(zipFile); // 输出到页面
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(20001, "文件不存在或者文件不可读或者文件是目录");
        }
    }

    public static byte[] zipFile(Map<String, List<String>> map, String baseName, HttpServletResponse response) throws IOException {
        List<String> name = new ArrayList<>();
        ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());//创建压缩输出流
        zos.setMethod(ZipOutputStream.DEFLATED); //设置压缩方法，进行压缩存储
        try {
            byte[] buffer = null;
            Set<String> keys  = map.keySet();
            for(String key:keys){
                for (int i = 0; i < map.get(key).size(); i++) {
                    File f = new File(map.get(key).get(i));

////                        String[] fileCreatTimeTempSplit = map.get(key).get(i).split("\\/");//linux远程服务器端
//                        String[] fileCreatTimeTempSplit = map.get(key).get(i).split("\\\\");//本地服务器
                    String[] fileCreatTimeTempSplit = map.get(key).get(i).replaceAll("\\\\","/").split("/");
                    if(fileCreatTimeTempSplit[fileCreatTimeTempSplit.length-1]=="zipName"){
                        fileCreatTimeTempSplit[fileCreatTimeTempSplit.length-1]+=".zip";
                    }
                         String fileCreatTime = fileCreatTimeTempSplit[fileCreatTimeTempSplit.length-2];

                    if (!f.exists()) {
                        continue;}
                    else{
                        name.add(f.getName());
                        String pathName = (map.get(key).get(0).contains("file-three")||map.get(key).get(0).contains("file-foot"))?(key+"的"+baseName+"/"+fileCreatTime + "-" + f.getName()):(key+"的"+baseName+"/" + f.getName());
                        zos.putNextEntry(new ZipEntry(pathName));
                        FileInputStream fis = new FileInputStream(f);
                        buffer = new byte[1024*10];
                        int r = 0;
                        while ((r = fis.read(buffer)) != -1) zos.write(buffer, 0, r);
                        fis.close();
                    }
                }
            }
            System.out.println("成功打包下载"+name.size()+"份"+baseName);
            return buffer;
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyException(20001, "文件不存在或者文件不可读或者文件是目录");
        } finally {     // 必须释放和关闭，否则可能会出现压缩的文件出现损坏。
            zos.flush();
            zos.close();
        }
    }

    /**
     * 压缩成ZIP 方法2
     * @param srcFiles 需要压缩的文件列表
     * @param out 	        压缩文件输出流
     * @throws RuntimeException 压缩失败会抛出运行时异常
     */
    public static void toZip(List<File> srcFiles , OutputStream out)throws RuntimeException {
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null ;
        try {
            zos = new ZipOutputStream(out);
            for (File srcFile : srcFiles) {
                byte[] buf = new byte[2 * 1024];
                zos.putNextEntry(new ZipEntry(srcFile.getName()));
                int len;
                FileInputStream in = new FileInputStream(srcFile);
                while ((len = in.read(buf)) != -1){
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                in.close();
            }
            long end = System.currentTimeMillis();
            System.out.println("压缩完成，耗时：" + (end - start) +" ms");
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils",e);
        }finally{
            if(zos != null){
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
